package com.marketlive.entity;

/*
(C) Copyright MarketLive. 2006. All rights reserved.
MarketLive is a trademark of MarketLive, Inc.
Warning: This computer program is protected by copyright law and international treaties.
Unauthorized reproduction or distribution of this program, or any portion of it, may result
in severe civil and criminal penalties, and will be prosecuted to the maximum extent
possible under the law.
*/

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.marketlive.entity.IComplexAttribute;
import org.marketlive.entity.IComplexAttributePage;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * Base class for complex attribute pages. Complex attribute pages provide the ability to
 * add attributes to entities, including collections of attributes.
 *
 * @see org.marketlive.entity.IAttributePage
 * @see org.marketlive.entity.IComplexAttribute
 */
public abstract class ComplexAttributePage extends AttributePage implements IComplexAttributePage {

    private static Log log = LogFactory.getLog(ComplexAttributePage.class);
    
    /**
     * Default constructor. Provided for use by the persistence layer.
     */
    public ComplexAttributePage() {
    }

    /**
     * Returns a new instance of complex attribute types. Available types
     * are defined in the attribute page implementation, which is configured from the home object of
     * the entity it is assigned to.
     *
     * @param attributeName the name of the attribute to retrieve
     * @param attributeDefinitions the known attribute definitions
     * @return the <code>IComplexAttribute</code> with the given attribute name
     * @throws RuntimeException if the attribute type is not defined or if a new instance cannot be instantiated
     */
    public static IComplexAttribute getAttributeInstance(final String attributeName, final Map attributeDefinitions) {
        IComplexAttribute attribute;
        Class attributeClass = (Class) attributeDefinitions.get(attributeName);
        if (attributeClass == null) {
            throw new RuntimeException("Complex attribute type not defined: " + attributeName);
        }
        try {
            attribute = (IComplexAttribute) attributeClass.newInstance();
        } catch (Exception e) {
            throw new RuntimeException("Failed to instantiate complex attribute type:" + attributeName);
        }

        return attribute;
    }
    
    /**
     * {@inheritDoc}
     */
//    public boolean isEmpty() { 
//        Method method = null;
//        try {
//            BeanInfo beanInfo = Introspector.getBeanInfo(this.getClass());
//            MethodDescriptor[] methods = beanInfo.getMethodDescriptors();
//      
//            for (int i = 0; i < methods.length; i++) {
//                MethodDescriptor methodDescriptor = (MethodDescriptor) methods[i];
//                method = methodDescriptor.getMethod();
//                String methodName = method.getName();
//                if (!methodName.equals("getAttributeInstance")){
//                    super.isEmpty();
//                }
//            }     
//        } catch (IntrospectionException e) {
//            log.error("Introspection exception occurred attempting to introspect bean:" + this + " method: " + method.getName());
//        } catch (Exception e) {
//            log.error("Reflection exception occurred attempting to introspect bean:" + this + " method: " + method.getName());
//        }
//        return true;
//    }
//    public boolean isEmpty() { 
//        Method method = null;
//        try {
//            BeanInfo beanInfo = Introspector.getBeanInfo(this.getClass());
//            MethodDescriptor[] methods = beanInfo.getMethodDescriptors();
//      
//            for (int i = 0; i < methods.length; i++) {
//                MethodDescriptor methodDescriptor = (MethodDescriptor) methods[i];
//                method = methodDescriptor.getMethod();
//                String methodName = method.getName();
//                Class returnType = method.getReturnType();
//
//                // Only invoke getter methods named per the bean spec.
//                // - getClass is always the 1st method and always has an object reference.
//                // - getName will always return the name of the attribute Page - even if values are null
//                if ((methodName.startsWith("get") || methodName.startsWith("is")) &&
//                        (!methodName.equals("getClass")) &&
//                        (!methodName.equals("getName")) &&
//                        (!methodName.equals("isEmpty")) &&
//                        (!methodName.equals("getAttributeInstance"))) {
//
//                    Object value = method.invoke(this, (Object[]) null);
//                    
//                    if (value != null) {
//                        if (returnType.isInstance(new String())){
//                          return value.equals("");  
//                        } 
//                        return false;
//                    }
//                }
//            }
//        } catch (IntrospectionException e) {
//            log.error("Introspection exception occurred attempting to introspect bean:" + this + " method: " + method.getName());
//        } catch (Exception e) {
//            log.error("Reflection exception occurred attempting to introspect bean:" + this + " method: " + method.getName());
//        }
//        return true;
//}

    /**
     * {@inheritDoc}
     */
    protected boolean isCallableMethod(String methodName){
        if (methodName.equals("getAttributeInstance")) return false;
        return super.isCallableMethod(methodName);
    }
}


